#!/usr/bin/env python3
VENDOR = b'StarFive Technology Co., Ltd.'

DEFAULT = (
    (  # header
        (b'SFVF', 4),  # signature
        (0x01, 1),     # version
        (0x00, 1),     # reversed
        (0x02, 2),     # numatoms
        (0x80, 4)      # eeplen
    ),
    (  # atom1
        (0x01, 2),     # type
        (0x01, 2),     # count
        (0x58, 4),     # dlen
        (0x00, 16),    # vendor info, uuid
        (0x00, 2),       # pid
        (0x00, 2),       # pver
        (0x20, 1),       # vslen
        (0x20, 1),       # pslen
        (VENDOR, 32),    # vstr
        ('#sn', 32),     # pstr
        ('@crc', 2)    # crc16
    ),
    (  # atom4
        (0x04, 2),     # type
        (0x02, 2),     # count
        (0x0c, 4),     # dlen
        (0x01, 2),     # custom data, version
        ('#pcb', 1),     # PCB version
        ('#bom', 1),     # BOM version
        ('#mac', 6),     # ether MAC
        ('@crc', 2)    # crc16
    )
)


def crc16(data, size):  # CRC16/ARC
    if data is None or size == 0:
        return 0

    crc = 0x0000
    for i in (range(0, size)):
        crc ^= data[i]
        for _ in range(0, 8):
            if (crc & 0x0001) > 0:
                crc = (crc >> 1) ^ 0xa001
            else:
                crc = crc >> 1
    return crc


def to_bytes(x, n):
    if isinstance(x, str):
        tmp = bytes.fromhex(x)
        tmp += bytes(n - len(tmp))
    elif isinstance(x, bytes):
        tmp = x + bytes(n - len(x))
    else:
        tmp = x.to_bytes(n, byteorder='little')
    return tmp


def make_eeprom(sn: bytes, mac: str, pcb: int=0x01, bom: int=0x41):
    eeprom = b''
    for item in DEFAULT:
        tmp = b''
        for val, n in item:
            if str(val).startswith('#'):
                val = vars()[val.strip('#')]
            elif str(val) == '@crc':
                val = crc16(tmp, len(tmp))
            tmp += to_bytes(val, n)
        eeprom += tmp
    return eeprom


def test_eppmake():
    mac = '6ccf3900002a'
    sn = b'VF7100A1-2201-D008E000-0000002B\x00'
    eeprom = make_eeprom(sn, mac)

    for i, x in enumerate(eeprom):
        print(f'{x:02x}', end=' ')
        if i % 16 == 15:
            print()

    print('\nWriting eeprom.dat')
    with open('eeprom.dat', 'wb') as f:
        f.write(eeprom)


if __name__ == '__main__':
    test_eppmake()
